using SharpGraphT.Graph;

namespace SharpGraphT;

public interface IGraph<TV, TE> : IGraph where TE : class, new() {
    IReadOnlySet<TE> GetAllEdges(TV sourceVertex, TV targetVertex);
    TE GetEdge(TV sourceVertex, TV targetVertex);
    Func<TV> VertexSupplier { get; }
    Func<TE> EdgeSupplier { get; }
    TE AddEdge(TV sourceVertex, TV targetVertex);
    bool AddEdge(TV sourceVertex, TV targetVertex, TE e);
    TV AddVertex();
    bool AddVertex(TV v);
    bool ContainsEdge(TV sourceVertex, TV targetVertex);
    bool ContainsEdge(TE e);
    bool ContainsVertex(TV v);
    IReadOnlySet<TE> EdgeSet { get; }
    int DegreeOf(TV vertex);
    IReadOnlySet<TE> EdgesOf(TV vertex);
    int InDegreeOf(TV vertex);
    IReadOnlySet<TE> IncomingEdgesOf(TV vertex);
    int OutDegreeOf(TV vertex);
    IReadOnlySet<TE> OutgoingEdgesOf(TV vertex);
    bool RemoveAllEdges<TEe>(IEnumerable<TEe> edges) where TEe : TE;
    IReadOnlySet<TE> RemoveAllEdges(TV sourceVertex, TV targetVertex);
    bool RemoveAllVertices<TVv>(ICollection<TVv> vertices) where TVv : TV;
    TE RemoveEdge(TV sourceVertex, TV targetVertex);
    bool RemoveEdge(TE e);
    bool RemoveVertex(TV v);
    IReadOnlySet<TV> VertexSet { get; }
    TV GetEdgeSource(TE e);
    TV GetEdgeTarget(TE e);
    IGraphType Type { get; }
    double GetEdgeWeight(TE e);
    void SetEdgeWeight(TE e, double weight);

    void SetEdgeWeight(TV sourceVertex, TV targetVertex, double weight) {
        SetEdgeWeight(GetEdge(sourceVertex, targetVertex), weight);
    }

    IGraphIterables<TV, TE> Iterables => new DefaultGraphIterables<TV, TE>(this);

    bool GraphEquals(IGraph<TV, TE> graph);
}

public interface IGraph {
    const double DefaultEdgeWeight = 1.0;
}